home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 2181 < prev    next >
Encoding:
Text File  |  1996-08-06  |  3.2 KB  |  112 lines

  1. Path: news.th-darmstadt.de!news
  2. From: Enno Sandner <enno@intellektik.informatik.th-darmstadt.de>
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: Smart Pointer Implementation & question
  5. Date: Tue, 16 Jan 1996 10:16:59 +0100
  6. Organization: Fachbereich Informatik, TH Darmstadt
  7. Message-ID: <30FB6D0B.167EB0E7@intellektik.informatik.th-darmstadt.de>
  8. References: <4dfe36$d99@grid.direct.ca>
  9. NNTP-Posting-Host: kitz.intellektik.informatik.th-darmstadt.de
  10. Mime-Version: 1.0
  11. Content-Type: text/plain; charset=us-ascii
  12. Content-Transfer-Encoding: 7bit
  13. X-Mailer: Mozilla 2.0b5 (X11; I; SunOS 4.1.3 sun4m)
  14.  
  15. Ken Clark wrote:
  16. > Hi.  I have implemented a reference counting smart pointer class.  It works
  17. > well, except that I can't get a basic behavior of normal pointers: automatic
  18. > casting of subclass pointers.  Consider class shape and subclass circle.  I
  19. > can do
  20. >         shape *s;
  21. >         circle *c;
  22. >         ...
  23. >         s = c;
  24. > What I want to be able to do (with the same semantics)
  25. >         RCPtr<shape> s;
  26. >         RCPtr<circle> c;
  27. >         ...
  28. >         s = c;
  29. > I think I understand why I can't do this (Stoustrup's square peg in round hole
  30. > analogy).  My question is, how do I get this behavior if that is what I want?
  31. > I have included the class below.  Any other suggestions on how to improve it
  32. > are appreciated.  Feel free to use the class in your code if you like.
  33. > Thanks,
  34. > - Ken
  35. > template <class T>
  36. > class RCPtr {
  37. >         struct RCPtrRep {
  38. >                 T *p;
  39. >                 unsigned count;
  40. >                 RCPtrRep(T* ip = 0)     { p = ip; count = 1; }
  41. >                 ~RCPtrRep()             { delete p; }
  42. >         } *rep;
  43. > public:
  44. >         RCPtr(T *ip = 0)                { rep = new RCPtrRep(ip); }
  45. >         RCPtr& operator=(T *ip)
  46. >         {
  47. >                 RCPtr::~RCPtr();
  48. >                 rep = new RCPtrRep(ip);
  49. >                 return *this;
  50. >         }
  51. >         RCPtr& operator=(const RCPtr& rip)
  52. >         {
  53. >                 rip.rep->count++;
  54. >                 RCPtr::~RCPtr();
  55. >                 rep = rip.rep;
  56. >                 return *this;
  57. >         }
  58. >         ~RCPtr()
  59. >         {
  60. >                 if (--rep->count == 0) delete rep;
  61. >         }
  62. >         T *operator->()                 { return (T *)rep->p; }
  63. >         T& operator*()                  { return *(T *)rep->p; }
  64. > };
  65.  
  66. I think in theory (ie. according to the DWP) you can have a templated
  67. conversion operator in the class:
  68.  
  69.       template<class T> class RCPtr { 
  70.             ...
  71.  
  72.           template<class S> operator RCPtr<S>() const {
  73.             S* s=dynamic_cast<S*>(rep->p);
  74.             return RCPtr<S>(s ? new S(*s) : 0);
  75.           }
  76.       };
  77.  
  78. Anyway this will not work on any compiler these days.
  79. A workarround is an auxilary templated function, that does the job.
  80. Both solutions exspect that the RCPtr class can properly handle
  81. null-pointers.
  82. In addition your class can lead to unwanted modifications. For example:
  83.  
  84. struct A { 
  85.   A() : valid_(true) {} 
  86.   bool valid_;
  87. };
  88.  
  89. int main()
  90. {
  91.   RCPtr<A> pa1(new A());
  92.   RCPtr<A> pa2=pa1;
  93.   pa1->valid_=false;
  94.  
  95. // pa1->valid_==false && pa2->valid_==false
  96. }
  97.  
  98. will modify _both_ instances.
  99. Can can remove this problem if you clone the maintained instance every
  100. time
  101. the wrapper returns a non-const pointer or reference to it.
  102.  
  103.            Enno
  104.